
#include <stdio.h>
#include <stdint.h>
#include <libxml/encoding.h>
#include <libxml/xmlwriter.h>
#include "account.h"

const char *account_method[] = {
  [ACCOUNT_METHOD_RESPONSE] = "response",

  [ACCOUNT_METHOD_VERSION]        = "version",
  [ACCOUNT_METHOD_VERSION_HANDLE] = "version_handle",

  [ACCOUNT_METHOD_SIGN_IN]        = "sign_in",
  [ACCOUNT_METHOD_SIGN_IN_HANDLE] = "sign_in_handle",

  [ACCOUNT_METHOD_SIGN_UPDATE]        = "sign_update",
  [ACCOUNT_METHOD_SIGN_UPDATE_HANDLE] = "sign_update_handle",

  [ACCOUNT_METHOD_SIGN_UP_GET_ID]         = "sign_up_get_id",
  [ACCOUNT_METHOD_SIGN_UP_GET_ID_HANDLE]  = "sign_up_get_id_handle",

  [ACCOUNT_METHOD_SIGN_UP]        = "sign_up",
  [ACCOUNT_METHOD_SIGN_UP_HANDLE] = "sign_up_handle",

  [ACCOUNT_METHOD_GET_INFO]         = "get_info",
  [ACCOUNT_METHOD_GET_INFO_HANDLE]  = "get_info_handle",

  [ACCOUNT_METHOD_GET_OTHER_INFO]         = "get_other_info",
  [ACCOUNT_METHOD_GET_OTHER_INFO_HANDLE]  = "get_other_info_handle",

  [ACCOUNT_METHOD_GET_CONTACTS]         = "get_contacts",
  [ACCOUNT_METHOD_GET_CONTACTS_HANDLE]  = "get_contacts_handle",

  [ACCOUNT_METHOD_GET_CONTACT_MSG]        = "get_contact_msg",
  [ACCOUNT_METHOD_GET_CONTACT_MSG_HANDLE] = "get_contact_msg_handle",

  [ACCOUNT_METHOD_SEND_MSG]         = "send_msg",
  [ACCOUNT_METHOD_SEND_MSG_HANDLE]  = "send_msg_handle",
};
const char *account_status[] = {
  [ACCOUNT_STATUS_DISCONNECTED]        = "network is error or not exist",
  [ACCOUNT_STATUS_ERROR_SIGN]           = "id or pwd error",
  [ACCOUNT_STATUS_SUCCESS_SIGN]         = "sign in success",
  [ACCOUNT_STATUS_SUCCESS_GET_CONTACTS] = "get contacts success",
};
const char *account_button[] = {
  [ACCOUNT_STATUS_ERROR_SIGN]           = "sign in",
  [ACCOUNT_STATUS_SUCCESS_SIGN]         = "sign out",
  [ACCOUNT_STATUS_SUCCESS_GET_CONTACTS] = "sign out",
};
const char *account_status_to_str(int status)
{
  return account_status[status];
}
const char *account_status_to_button(int status)
{
  return account_button[status];
}
#if 0
void *account_get_socket(void *sql, const char *id)
{
  void *res = NULL;
  char statement[1024] = {0};
  const char *obj_str = NULL;
  JsonObject *obj = NULL;
  JsonArray *array_data = NULL, *array_value = NULL;

  snprintf(statement, sizeof(statement),
      "select %s from %s where id=%s;",
      ACCOUNT_FIELD_SOCKET, ACCOUNT_TABLE_ACCOUNT, id);
  obj = sql_exec(sql, statement);
  array_data = json_object_get_array_member(obj, "data");
  array_value = json_array_get_array_element(array_data, 1);
  obj_str = json_array_get_string_element(array_value, 0);
  g_debug("%s[%d]%s\n", __FILE__, __LINE__, obj_str);
  if (obj_str) {
    res = (void *)(intptr_t)atoll(obj_str);
  }
  goto out;
out:
  return res;
}
int account_get_limits(void *sql, const char *id, const char *listener)
{
  int rc = 0;
  
  rc = 1;

  return rc;
}
/*
int account_server_send_to_client_msg(void *sql, const char *id,
    void *obj_unit, const char *time_str, void *param)
{
  const char *obj_str = NULL;
  int rc = 0;
  void *socket = NULL;
  sys_send_fc tmp_send_fc = NULL;
  JsonObject *obj = NULL, *obj_send_unit = NULL, *array_data = NULL;
  JsonArray *array_data = NULL;

  tmp_send_fc = param;
  socket = account_get_socket(sql, id);
  if (socket) {
    //TODO
    array_data = json_object_get_array_member(obj, "data");
  //  json_deep_copy(obj_unit, &obj_send_unit, NULL);
    json_array_add(array_data, obj_send_unit);
    json_object_add(obj_send_unit, "time",
        json_new_string(time_str));
    obj_str = json_get_string(obj);
    tmp_send_fc(socket, (uint8_t *)obj_str, strlen(obj_str));
    if (obj)
      json_object_unref (obj);
    if (rc != strlen(obj_str)) {
      rc = 0;
    } else {
      rc = 1;
    }
  }
  return rc;
}
*/
int account_method_to_int(const char *src)
{
  int rc = 0, i, sum;
  const char *tmp = NULL;

  sum = ACCOUNT_METHOD_END;
  for (i = 0; i < sum; i++) {
    tmp = account_method[i];
    if (tmp) {
      if (strcmp(tmp, src) == 0) {
        break;
      }
    }
  }
  rc = i;

  return rc;
}
void *account_json_init(const char *version)
{
  void *obj = NULL;

  if (!version) {
    g_warning("version is NULL\n");
    goto err;
  }
  obj = json_object_new();
  if (version)
    json_object_set_string_member(obj, "version", version);
err:
  return obj;
}
/*
void *account_msg_json_analysis(void *obj, const char **speaker_p,
    const char **listener_p, const char **msg_p,
    int *status_p, uint64_t *time_p)
{
  void *res = NULL;
  const char *obj_str = NULL;
  void *obj_tmp = NULL;

  obj_tmp = json_object_get(obj, ACCOUNT_FIELD_ID);
  *speaker_p = json_get_string(obj_tmp);
  obj_tmp = json_object_get(obj, ACCOUNT_FIELD_PEER_ID);
  *listener_p = json_get_string(obj_tmp);
  obj_tmp = json_object_get(obj, "msg");
  *msg_p = json_get_string(obj_tmp);
  obj_tmp = json_object_get(obj, "status");
  obj_str = json_get_string(obj_tmp);
  *status_p = atoi(obj_str);
  obj_tmp = json_object_get(obj, "time");
  obj_str = json_get_string(obj_tmp);
  *time_p = atoll(obj_str);

  return res;
}
void *account_no_sign(void)
{
  JsonObject *obj = NULL;
//TODO
  json_object_add(obj, "error",
      json_new_string("need sign in"));
  return obj;
}
*/
int account_exist_id(void *sql, const char *id)
{
  char statement[1024] = {0};
  int rc = 0;

  snprintf(statement, sizeof(statement),
      "select 1 from '%s' where id = '%s' limit 1;",
      ACCOUNT_TABLE_ACCOUNT, id);
  rc = sql_exec_count(sql, statement);

  return rc;
}
int account_sql_check_id_pwd(void *sql, const char *table_name,
    const char *id, const char *pwd)
{
  char statement[1024] = {0};
  //const char *obj_str = NULL;
  int rc = 0, sum = 0;
  JsonObject *obj = NULL;
  JsonArray *array_data = NULL;

  snprintf(statement, sizeof(statement),
      "select * from %s where id=%s and pwd='%s';",
      table_name, id, pwd);
  obj = sql_exec(sql, statement);
  array_data = json_object_get_array_member(obj, "data");
  sum = json_array_get_length(array_data);
  if (sum > 1) {
  } else {
    rc = ENOMSG;
    goto out;
  }
out:
  if (obj)
    json_object_unref (obj);
  return rc;
}
int account_sign_in_handle(void *sql, void *obj, void *user_data)
{
  int rc = 0;
  char statement[1024] = {0};
  const char *id = NULL, *pwd = NULL;
  void *obj_unit = NULL, *obj_sql = NULL, *array_data = NULL;

  array_data = json_object_get_array_member(obj, "data");
  obj_unit = json_array_get_object_element(array_data, 0);
  id = json_object_get_string_member(obj_unit, "id");
  pwd = json_object_get_string_member(obj_unit, "pwd");
//obj_send
  rc = account_sql_check_id_pwd(sql, ACCOUNT_TABLE_ACCOUNT, id, pwd);
  if (!rc) {
    snprintf(statement, sizeof(statement),
        "update %s set %s=%ld where id=%s;",
        ACCOUNT_TABLE_ACCOUNT, ACCOUNT_FIELD_SOCKET,
        (uint64_t)(intptr_t)user_data, id);
    g_debug("%s[%d]%p\t%s\n", __FILE__, __LINE__, user_data, statement);
    obj_sql = sql_exec(sql, statement);
    if (obj_sql) {
      //g_warning("%s\n", json_get_string(obj_sql));
    }
  }
  goto out;
out:
  if (obj_sql)
    json_object_unref (obj_sql);
  return rc;
}
int account_get_other_info_handle(void *sql, void *obj, void *obj_send)
{
  int rc = 0;
  char statement[1024] = {0};
  const char *id = NULL;
//obj_read
  id = json_object_get_string_member(obj, ACCOUNT_FIELD_PEER_ID);
  if (!id) {
    goto out;
  }
  snprintf(statement, sizeof(statement),
      "select id,nickname,email,contact from %s where id=%s;",
      ACCOUNT_TABLE_ACCOUNT, id);
  obj_send = sql_exec(sql, statement);
out:
  return rc;
}
int account_get_info_handle(void *sql, void *obj, void *obj_send)
{
  int rc = 0;
  char statement[1024] = {0};
  const char *id = NULL;

  id = json_object_get_string_member(obj, ACCOUNT_FIELD_PEER_ID);
  if (!id) {
    goto err;
  }
  snprintf(statement, sizeof(statement),
      "select id,nickname,email,contact from %s where id=%s;",
      ACCOUNT_TABLE_ACCOUNT, id);
//obj_send
  obj_send = sql_exec(sql, statement);
err:
  return rc;
}
int account_sign_up_handle(void *sql, void *obj, void *socket)
{
  int rc = 0;
  char buf[1024] = {0}, statement[1024] = {0};
  const char *nickname = NULL, *pwd = NULL, *email = NULL,
        *contact = NULL, *id = NULL, *error_str = NULL;
  JsonObject *obj_sql = NULL;

  if (obj == NULL) {
    rc = ENODATA;
    goto err;
  }
  id = json_object_get_string_member(obj, ACCOUNT_FIELD_PEER_ID);
  if (!id) {
    rc = ENOMSG;
    g_error("no id\n");
    goto err;
  }
  if (!account_exist_id(sql, id)) {
    rc = EEXIST;
    g_error("exist id:%s\n", id);
    goto err;
  }
  pwd = json_object_get_string_member(obj, "pwd");
  if (!pwd) {
    rc = ENOMSG;
    g_error("no pwd\n");
    goto err;
  }
  nickname = json_object_get_string_member(obj, "nickname");
  if (!nickname) {
    g_warning("no nickname\n");
  }
  email = json_object_get_string_member(obj, "email");
  //TODO SEND CONFIRM CODE to email
  contact = json_object_get_string_member(obj, "contact");
  snprintf(statement, sizeof(statement),
      "insert into %s (id,pwd,nickname,email,contact) values (%s,'%s','%s','%s','%s');",
      ACCOUNT_TABLE_ACCOUNT, id, pwd,
      nickname, email, contact);
  obj = sql_exec(sql, statement);
  error_str = json_object_get_string_member(obj, "error");
  if (error_str) {
  } else {
    //TODO update socket
    snprintf(buf, sizeof(buf), "%d", g_random_int());
    snprintf(statement, sizeof(statement),
        "update %.16s set token=\"%.32s\",time=%ld where id=%.16s;",
        ACCOUNT_TABLE_ACCOUNT, buf,
        time(NULL), id);
    obj_sql = sql_exec(sql, statement);
  }
err:
  if (obj_sql)
    json_object_unref (obj_sql);
  return rc;
}
int account_sign_update_handle(void *sql, void *obj)
{
  int rc = 0;
  char statement[1024] = {0};
  const char *nickname = NULL, *pwd = NULL, *email = NULL,
        *contact = NULL, *id = NULL;
  void *obj_sql = NULL;
//obj_read
  id = json_object_get_string_member(obj, "id");
  pwd = json_object_get_string_member(obj, "pwd");
  nickname = json_object_get_string_member(obj, "nickname");
  email = json_object_get_string_member(obj, "email");
  contact = json_object_get_string_member(obj, "contact");
//obj_send
  snprintf(statement, sizeof(statement),
      "update %s set pwd='%s',nickname='%s',email='%s',contact='%s' where id=%s;",
      ACCOUNT_TABLE_ACCOUNT, pwd, nickname, email, contact,
      id);
  //TODO
  obj_sql = sql_exec(sql, statement);
  goto out;
out:
  if (obj_sql)
    g_object_unref (obj_sql);
  return rc;
}
uint64_t account_sign_up_get_id_handle(void *sql)
{
  uint64_t rc = 0;
  char statement[1024] = {0};
  const char *obj_str = NULL;
  JsonObject *obj = NULL, *obj_unit = NULL;
  JsonArray *array_data = NULL;

  snprintf(statement, sizeof(statement),
      "select max(id) from %s;", ACCOUNT_TABLE_ACCOUNT);
  obj = sql_exec(sql, statement);
  array_data = json_object_get_array_member(obj, "data");
  obj_unit = json_array_get_object_element(array_data, 0);
  obj_str = json_object_get_string_member(obj_unit, "max(id)");
  rc = atoll(obj_str) + 1;

  return rc;
}
int account_get_contacts_handle(void *sql, void *obj, void *obj_send)
{
  int rc = 0;
  char statement[1024] = {0};
  const char *id = NULL;
  void *array_data = NULL, *obj_sql = NULL, *node = NULL;

//obj_read
  id = json_object_get_string_member(obj, "id");
  if (!id) {
    g_error("\n");
    goto err;
  }
//obj_send
  snprintf(statement, sizeof(statement),
      "select %s.id,nickname,email,contact,alias,sys_type from %s,contacts_%s where %s.id=contacts_%s.id;",
      ACCOUNT_TABLE_ACCOUNT, ACCOUNT_TABLE_ACCOUNT,
      id, ACCOUNT_TABLE_ACCOUNT, id);
  obj_sql = sql_exec(sql, statement);
  node = json_object_dup_member(obj_sql, "data");
  array_data = json_node_get_array(node);
  json_object_set_array_member(obj_send, "data", array_data);
err:
  if (obj_sql)
    json_object_unref (obj_sql);
  return rc;
}
int account_json_send_msg_handle(void *socket, void *sql, void *obj, void *param)
{
  int rc = 0, sum = 0, i = 0;
  char time_str[32] = {0};
  const char *speaker = NULL, *id = NULL,
        *msg = NULL, *listener_str = NULL;
  uint64_t time_uint64 = 0;
  void *obj_unit = NULL, *array_data = NULL;
  
  time_uint64 = time(NULL);
  snprintf(time_str, sizeof(time_str), "%ld", time_uint64);
//obj_read
  id = json_object_get_string_member(obj, "id");
  array_data = json_object_get_array_member(obj, "data");
  if (!array_data) {
    goto err;
  }
  sum = json_array_get_length(array_data);
  for (i = 0; i < sum; i++) {
    obj_unit = json_array_get_object_element(array_data, i);
    speaker = json_object_get_string_member(obj_unit, ACCOUNT_FIELD_ID);
    if (!speaker) {
      g_error("\n");
      goto err;
    }
    listener_str = json_object_get_string_member(obj_unit, ACCOUNT_FIELD_PEER_ID);
    if (!listener_str) {
      g_error("\n");
      goto err;
    }
    msg = json_object_get_string_member(obj_unit, "msg");
    if (!msg) {
      g_error("\n");
      goto err;
    }
  //obj_send
    rc = account_get_limits(sql, id, listener_str);
    if (rc) {
      rc = account_send_listener_msg(sql, listener_str, msg, speaker, param);
    }
  }
err:
  return rc;
}
int account_send_listener_msg(void *sql, const char *listener, const char *msg,
    const char *speaker, void *param)
{
  int rc = 0;
  void *socket = NULL;
  char statement[1024] = {0}, time_str[32] = {0};
  //const char *obj_str = NULL;
  uint64_t time_uint64 = 0;
  void *obj = NULL, *obj_sql = NULL, *array_data = NULL;

  socket = account_get_socket(sql, listener);
  if (!socket) {
    rc = EIO;
    goto err;
  }
  time_uint64 = time(NULL);
  snprintf(time_str, sizeof(time_str), "%ld", time_uint64);
  obj = account_json_init(ACCOUNT_VERSION);
  array_data = json_array_new();
  json_object_set_array_member(obj, ACCOUNT_FIELD_DATA, array_data);
  //json_array_add(array_data, account_json_send_msg(
    //    speaker, msg, listener));
  //TODO send msg to peer
  //obj_str = json_get_string(obj);
  //tmp_send_fc(socket, (uint8_t *)obj_str, strlen(obj_str));
  snprintf(statement, sizeof(statement),
      "insert into msg_%s (time,speaker,listener,msg,status) values (%s,%s,%s,'%s',%d);",
      speaker, time_str, speaker, listener,
      msg, rc);
  obj_sql = sql_exec(sql, statement);
  if (obj_sql)
    json_object_unref (obj_sql);
  snprintf(statement, sizeof(statement),
      "insert into msg_%s (time,speaker,listener,msg,status) values (%s,%s,%s,'%s',%d);",
      listener, time_str, speaker, listener,
      msg, rc);
  obj_sql = sql_exec(sql, statement);
  if (obj_sql) {
    json_object_unref (obj_sql);
    obj_sql = NULL;
  }
err:
  return rc;
}
int account_sql_is_group(void *sql, const char *id)
{
  int rc = 0;
  char statement[1024] = {0};
  const char *obj_str = NULL;
  JsonObject *obj = NULL, *obj_unit = NULL;
  JsonArray *array_data = NULL;

  snprintf(statement, sizeof(statement),
      "select sys_type from %s where id=%s;",
      ACCOUNT_TABLE_ACCOUNT, id);
  obj = sql_exec(sql, statement);
  array_data = json_object_get_array_member(obj, "data");
  obj_unit = json_array_get_object_element(array_data, 0);
  obj_str = json_object_get_string_member (obj_unit, "sys_type");
  if (obj_str) {
    g_debug("sys_type:%s\n", obj_str);
    if (strcmp(obj_str, "group")) {
    } else {
      rc = 1;
    }
  }
  goto err;
err:
  if (obj)
    json_object_unref (obj);
  return rc;
}
void *account_json_add_msg_from_sql(void *obj,
    void *sql, const char *id, const char *peer)
{
  char statement[1024] = {0};
  JsonNode *node = NULL;
  JsonObject *obj_sql = NULL;
  JsonArray *array_data = NULL;

  if (account_sql_is_group(sql, peer)) {
    snprintf(statement, sizeof(statement),
        "select time,speaker,listener,msg,status from msg_%s order by time limit 10;",
        peer);
  } else {
    snprintf(statement, sizeof(statement),
        "select time,speaker,listener,msg,status from msg_%s where speaker=%s or listener=%s order by time limit 10;",
        id, peer, peer);
  }
  obj_sql = sql_exec(sql, statement);
  node = json_object_dup_member(obj_sql, "data");
  array_data = json_node_get_array(node);
  json_object_set_array_member(obj, "data", array_data);
  goto err;
err:
  if (obj_sql)
    json_object_unref (obj_sql);
  return obj;
}
/*
void *account_json_to_sql(void *sql, void *obj)
{
  int sum, i, method = 0;
  char statement[1024] = {0};
  const char *obj_str = NULL;
  void *obj_sql = NULL, *obj_tmp = NULL,
        *obj_unit = NULL, *array_data = NULL;
//obj_read
  array_data = json_object_get_array_member(obj, "data");
  if (array_data == NULL) {
    goto err;
  }
  sum = json_array_get_length(array_data);
  for (i = 0; i < sum; i++) {
    obj_unit = json_array_get_object_element(array_data, i);
    sql_insert_statement_from_field_json(obj_unit, "sign",
        statement, sizeof(statement));
    obj_sql = sql_exec(sql, statement);
    if (obj_sql) {
      obj_str = json_get_string(obj_sql);
      DEBUG("STATEMENT:%s\n", obj_str);
      obj_tmp = json_object_get(obj_sql, "error");
      json_object_unref (obj_sql);
      obj_sql = NULL;
      if (obj_tmp) {
        sql_update_statement_from_field_json(obj_unit,
            "sign", "id",
            statement, sizeof(statement));
        obj_sql = sql_exec(sql, statement);
        if (obj_sql) {
      obj_str = json_get_string(obj_sql);
      DEBUG("STATEMENT:%s\n", obj_str);
          json_object_unref (obj_sql);
          obj_sql = NULL;
        }
      }
    }
  }
  obj_tmp = json_object_get(obj, "method");
  obj_str = json_get_string(obj_tmp);
  method = account_method_to_int(obj_str);
  if (method == ACCOUNT_METHOD_VERSION_HANDLE) {
  } else if (method == ACCOUNT_METHOD_GET_CONTACTS_HANDLE) {
    sum = json_array_length(array_data);
    for (i = 0; i < sum; i++) {
      obj_unit = json_array_get_idx(array_data, i);
      obj_tmp = json_object_get(obj_unit, "id");
      obj_str = json_get_string(obj_tmp);
      snprintf(statement, sizeof(statement),
          "create table msg_%s (time varchar(255),speaker varchar(255),listener varchar(255),msg varchar(1024),status int);",
          obj_str);
      obj_sql = sql_exec(sql, statement);
      if (obj_sql) {
        obj_str = json_get_string(obj_sql);
        DEBUG("STATEMENT:%s\n", obj_str);
        json_object_unref (obj_sql);
        obj_sql = NULL;
      }
    }
  } else {
  }
err:
  return obj;
}
*/
void *account_json_get_contact_msg_handle(void *sql, void *obj_read, void *obj)
{
  const char *id = NULL, *peer = NULL;
  JsonArray *array_data = NULL;
  JsonObject *obj_unit = NULL;
//obj_read
  id = json_object_get_string_member(obj_read, "id");
  if (!id) {
    g_error("\n");
    goto err;
  }
  array_data = json_object_get_array_member(obj_read, "data");
  if (array_data == NULL) {
    goto err;
  }
  obj_unit = json_array_get_object_element(array_data, 0);
  if (obj_unit == NULL) {
    g_error("\n");
    goto err;
  }
  peer = json_object_get_string_member(obj_unit, ACCOUNT_FIELD_PEER_ID);
  account_json_add_msg_from_sql(obj, sql, id, peer);
err:
  return obj;
}
size_t account_handle_msg(void *socket, const uint8_t *msg, size_t len,
    void* sql, void *param)
{
  char buf[1024] = {0}, **data_p = NULL;
  const char *obj_str = NULL, *id = NULL, *version = NULL;
  int rc = 0, method = 0;
  void *res = NULL;
  void *obj_read = NULL, *obj_send = NULL;
  void *parser = NULL;
  void *gen = NULL, *root = NULL, *node = NULL;
  GError *error = NULL;

  data_p = param;
  *data_p = NULL;
  obj_send = account_json_init(ACCOUNT_VERSION);

  parser = json_parser_new ();
  json_parser_load_from_data(parser, (char *)msg, -1, &error);
  root = json_parser_get_root(parser);
  obj_read = json_node_get_object(root);
  if (!obj_read) {
    json_object_set_string_member(obj_send, "error", "is not json");
    goto out;
  }
  version = json_object_get_string_member(obj_read, "version");
  if (!version) {
    json_object_set_string_member(obj_send, "error",
        "no version");
    g_warning("json no version\n");
    goto out;
  }
  id = json_object_get_string_member(obj_read, "id");
  if (!id) {
    json_object_set_string_member(obj_send, "error", "no id");
    g_warning("no id\n");
    goto out;
  }
  json_object_set_string_member(obj_send, "id", id);
  obj_str = json_object_get_string_member(obj_read, "method");
  if (!obj_str) {
    json_object_set_string_member(obj_send, "error", "no method");
    g_warning("no method\n");
    goto out;
  }
  method = account_method_to_int(obj_str);
  if (method == ACCOUNT_METHOD_VERSION) {
    if (strcmp(ACCOUNT_VERSION, version)) {
      snprintf(buf, sizeof(buf), "have the latest version:%s", ACCOUNT_VERSION);
    } else {
      snprintf(buf, sizeof(buf), "your apps are up to date.");
    }
    json_object_set_string_member(obj_send, "warning", buf);
    goto out;
  } else if (method == ACCOUNT_METHOD_SIGN_IN) {
    rc = account_sign_in_handle(sql, obj_read, socket);
    json_object_set_string_member(obj_send, "method",
          account_method[ACCOUNT_METHOD_SIGN_IN_HANDLE]
          );
    if (rc) {
      json_object_set_string_member(obj_send, "error", "id or pwd is error");
      json_object_set_int_member(obj_send, "status", ACCOUNT_STATUS_ERROR_SIGN);
    } else {
      json_object_set_int_member(obj_send, "status", ACCOUNT_STATUS_SUCCESS_SIGN);
    }
    goto out;
  } else if (method == ACCOUNT_METHOD_SIGN_UP_GET_ID) {
    rc = account_sign_up_get_id_handle(sql);
    snprintf(buf, sizeof(buf), "%d", rc);
    json_object_set_string_member(obj_send, "response", buf);
    goto out;
  } else if (method == ACCOUNT_METHOD_SIGN_UP) {
    rc = account_sign_up_handle(sql, obj_read, socket);
    if (rc) {
      json_object_set_string_member(obj_send, "error", strerror(rc));
    } else {
      json_object_set_string_member(obj_send, "response", "sign up success");
    }
    goto out;
  } else {
    res = account_get_socket(sql, id);
    if (res != socket) {
      g_debug("%s[%d]res:%p,socket:%p\n", __FILE__, __LINE__, res, socket);
      json_object_set_string_member(obj_send, "error", "no sign in");
      goto out;
    }
  }
  //sign in
  if (method == ACCOUNT_METHOD_SIGN_IN) {
    //sign up
  } else if (method == ACCOUNT_METHOD_SIGN_UP_GET_ID) {
  } else if (method == ACCOUNT_METHOD_SIGN_UP) {
  } else if (method == ACCOUNT_METHOD_SIGN_UPDATE) {
    rc = account_sign_update_handle(sql, obj_read);
    if (rc) {
      json_object_set_string_member(obj_send, "error",
          strerror(rc));
    } else {
      json_object_set_string_member(obj_send, "response",
            "sign update success");
    }
    if (obj_send)
      json_object_set_string_member(obj_send, "method",
            account_method[ACCOUNT_METHOD_SIGN_UPDATE_HANDLE]);
    goto out;
  } else if (method == ACCOUNT_METHOD_GET_INFO) {
    rc = account_get_info_handle(sql, obj_read, obj_send);
    if (obj_send)
      json_object_set_string_member(obj_send, "method",
            account_method[ACCOUNT_METHOD_GET_INFO_HANDLE]);
  } else if (method == ACCOUNT_METHOD_GET_OTHER_INFO) {
    rc = account_get_other_info_handle(sql, obj_read, obj_send);
    if (obj_send)
      json_object_set_string_member(obj_send, "method",
            account_method[ACCOUNT_METHOD_GET_OTHER_INFO_HANDLE]);
  } else if (method == ACCOUNT_METHOD_GET_CONTACTS) {
    rc = account_get_contacts_handle(sql, obj_read, obj_send);
    json_object_set_string_member(obj_send, "method",
          account_method[ACCOUNT_METHOD_GET_CONTACTS_HANDLE]);
    json_object_set_int_member(obj_send, "status",
          ACCOUNT_STATUS_SUCCESS_GET_CONTACTS);
  } else if (method == ACCOUNT_METHOD_SEND_MSG) {
    rc = account_json_send_msg_handle(socket, sql, obj_read, param);
    if (rc == EIO)
      json_object_set_int_member(obj_send, "status", ACCOUNT_STATUS_MSG_UNREAD);
    else
      json_object_set_int_member(obj_send, "status", ACCOUNT_STATUS_MSG_READ);
    if (obj_send)
      json_object_set_string_member(obj_send, "method",
            account_method[ACCOUNT_METHOD_SEND_MSG_HANDLE]);
  } else if (method == ACCOUNT_METHOD_GET_CONTACT_MSG) {
    account_json_get_contact_msg_handle(sql, obj_read, obj_send);
    if (obj_send)
      json_object_set_string_member(obj_send, "method",
            account_method[ACCOUNT_METHOD_GET_CONTACT_MSG_HANDLE]);
  } else {
    g_error("METHOD INVALID:%d\n", method);
    goto out;
  }
out:
  gen = json_generator_new ();
  node = json_node_new(JSON_NODE_OBJECT);
  json_node_take_object(node, obj_send);
  json_generator_set_root(gen, node);
  *data_p = json_generator_to_data(gen, &len);
  g_debug("%s[%d]:%s\n", __FILE__, __LINE__, *data_p);
  if (gen)
    g_object_unref (gen);
  if (node)
    json_node_free (node);
  if (parser)
    g_object_unref (parser);
  return len;
}
//client
int account_client_message_parse(const uint8_t *msg, int len,
    int *method, int *status, void **result_p)
{
  int rc = 0;
  const char *obj_str = NULL;
  JsonParser *parser = NULL;
  JsonNode *root = NULL;
  JsonObject *object = NULL;
  GError *error = NULL;

  parser = json_parser_new ();
  json_parser_load_from_data(parser, (char *)msg, -1, &error);
  root = json_parser_get_root(parser);
  object = json_node_get_object(root);
  if (!object) {
    g_warning("NOT JSON:%s\n", msg);
    goto err;
  }
  obj_str = json_object_get_string_member(object, "method");
  *method = account_method_to_int(obj_str);
  *status = json_object_get_int_member(object, "status");
err:
  return rc;
}
void *account_client_sign_in(const char *id, const char *pwd)
{
  void *obj = NULL, *array_data = NULL, *obj_unit = NULL;
  char *data = NULL;
  size_t len = 0;
  void *gen = NULL, *node = NULL;

  obj = json_object_new();
  json_object_set_string_member(obj, "version", "1.0.0");
  json_object_set_string_member(obj, "id", id);
  json_object_set_string_member(obj, "method",
        account_method[ACCOUNT_METHOD_SIGN_IN]);
  array_data = json_array_new();
  json_object_set_array_member(obj, "data", array_data);
  obj_unit = json_object_new();
  json_array_add_object_element(array_data, obj_unit);
  json_object_set_string_member(obj_unit, "id", id);
  json_object_set_string_member(obj_unit, "pwd", pwd);
  
  gen = json_generator_new ();
  node = json_node_new(JSON_NODE_OBJECT);
  json_node_take_object(node, obj);
  json_generator_set_root(gen, node);
  data = json_generator_to_data(gen, &len);
  goto out;
out:
  //if (obj)
    //json_object_unref (obj);
  if (gen)
    g_object_unref (gen);
  if (node)
    json_node_free (node);
  return data;
}
void *account_client_get_contacts(const char *id)
{
  void *obj = NULL, *array_data = NULL, *obj_unit = NULL;
  char *data = NULL;
  size_t len = 0;
  void *gen = NULL, *node = NULL;
  
  obj = json_object_new();
  json_object_set_string_member(obj, "version", "1.0.0");
  json_object_set_string_member(obj, "id", id);
  json_object_set_string_member(obj, "method",
        account_method[ACCOUNT_METHOD_GET_CONTACTS]);
  array_data = json_array_new();
  json_object_set_array_member(obj, "data", array_data);
  obj_unit = json_object_new();
  json_array_add_object_element(array_data, obj_unit);
  json_object_set_string_member(obj_unit, "id", id);

  gen = json_generator_new ();
  node = json_node_new(JSON_NODE_OBJECT);
  json_node_take_object(node, obj);
  json_generator_set_root(gen, node);
  data = json_generator_to_data(gen, &len);
  goto out;
out:
  if (gen)
    g_object_unref (gen);
  if (node)
    json_node_free (node);
  return data;
}
void *account_client_get_contact_msg(const char *id, const char *peer_id)
{
  void *obj = NULL, *array_data = NULL, *obj_unit = NULL;
  char *data = NULL;
  size_t len = 0;
  void *gen = NULL, *node = NULL;
  
  obj = json_object_new();
  json_object_set_string_member(obj, "version", "1.0.0");
  json_object_set_string_member(obj, "id", id);
  json_object_set_string_member(obj, "method",
        account_method[ACCOUNT_METHOD_GET_CONTACT_MSG]);
  array_data = json_array_new();
  json_object_set_array_member(obj, "data", array_data);
  obj_unit = json_object_new();
  json_array_add_object_element(array_data, obj_unit);
  json_object_set_string_member(obj_unit, ACCOUNT_FIELD_PEER_ID, peer_id);

  gen = json_generator_new ();
  node = json_node_new(JSON_NODE_OBJECT);
  json_node_take_object(node, obj);
  json_generator_set_root(gen, node);
  data = json_generator_to_data(gen, &len);
  goto out;
out:
  if (gen)
    g_object_unref (gen);
  if (node)
    json_node_free (node);
  return data;
}
void *account_client_send_msg(const char *id, const char *msg,
    const char *listener)
{
  void *obj = NULL, *array_data = NULL, *obj_unit = NULL;
  char *data = NULL;
  size_t len = 0;
  void *gen = NULL, *node = NULL;

  obj = json_object_new();
  json_object_set_string_member(obj, "version", "1.0.0");
  json_object_set_string_member(obj, "id", id);
  json_object_set_string_member(obj, "method",
        account_method[ACCOUNT_METHOD_SEND_MSG]);
  array_data = json_array_new();
  json_object_set_array_member(obj, "data", array_data);
  obj_unit = json_object_new();
  json_array_add_object_element(array_data, obj_unit);
  json_object_set_string_member(obj_unit, ACCOUNT_FIELD_ID, id);
  json_object_set_string_member(obj_unit, ACCOUNT_FIELD_PEER_ID, listener);
  json_object_set_string_member(obj_unit, "msg", msg);

  gen = json_generator_new ();
  node = json_node_new(JSON_NODE_OBJECT);
  json_node_take_object(node, obj);
  json_generator_set_root(gen, node);
  data = json_generator_to_data(gen, &len);
  goto out;
out:
  if (gen)
    g_object_unref (gen);
  if (node)
    json_node_free (node);
  return data;
}
void *account_sign_up_get_id(void)
{
  uint64_t id = 0;
  char buf[1024] = {0};
  JsonObject *obj = NULL;

  snprintf(buf, sizeof(buf), "%ld", id);
  //TODO
  
  return obj;
}
void *account_sign_update(const char *id, const char *pwd,
    const char *nickname, const char *email, const char *contact)
{
  void *obj = NULL, *array_data = NULL, *obj_unit = NULL;

  //TODO
  array_data = json_object_get_array_member(obj, "data");
  obj_unit = json_object_new();
  json_array_add_object_element(array_data, obj_unit);
  json_object_set_string_member(obj_unit, "id", id);
  if (pwd)
    json_object_set_string_member(obj_unit, "pwd", pwd);
  if (nickname)
    json_object_set_string_member(obj_unit, "nickname", nickname);
  if (email)
    json_object_set_string_member(obj_unit, "email", email);
  if (contact)
    json_object_set_string_member(obj_unit, "contact", contact);
  return obj;
}
void *account_sign_up(const char *id, const char *pwd, const char *nickname,
    const char *email, const char *contact)
{
  void *obj = NULL, *array_data = NULL, *obj_unit = NULL;

  //TODO
  array_data = json_object_get_array_member(obj, "data");
  obj_unit = json_object_new();
  json_array_add_object_element(array_data, obj_unit);
  json_object_set_string_member(obj_unit, "id", id);
  json_object_set_string_member(obj_unit, "pwd", pwd);
  json_object_set_string_member(obj_unit, "nickname", nickname);
  json_object_set_string_member(obj_unit, "email", email);
  json_object_set_string_member(obj_unit, "contact", contact);
  return obj;
}
void *account_get_info(const char *id)
{
  void *obj = NULL, *array_data = NULL, *obj_unit = NULL;

  //TODO
  array_data = json_object_get_array_member(obj, "data");
  obj_unit = json_object_new();
  json_array_add_object_element(array_data, obj_unit);
  json_object_set_string_member(obj_unit, "id", id);

  return obj;
}
void *account_get_other_info(const char *id)
{
  void *obj = NULL, *array_data = NULL, *obj_unit = NULL;

  //TODO
  array_data = json_object_get_array_member(obj, "data");
  obj_unit = json_object_new();
  json_array_add_object_element(array_data, obj_unit);
  json_object_set_string_member(obj_unit, "id", id);

  return obj;
}
#endif
